package org.budo.weixin.work.api.entity;

import java.io.Serializable;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.budo.support.fastjson.Fastjson;
import org.budo.support.http.client.MultipartEntity;
import org.budo.support.java.net.util.JavaNetUrlUtil;
import org.budo.support.lang.util.MapUtil;
import org.budo.support.lang.util.NumberUtil;
import org.budo.support.lang.util.StringUtil;
import org.budo.time.Time;
import org.budo.weixin.work.api.WorkWeixinApi;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;

/**
 * 审批模版控件
 * 
 * @author lmw
 */
@Getter
@Setter
@ToString
@Slf4j
public class TemplateContent implements Serializable {
    private static final long serialVersionUID = -5682329765621028040L;

    private JSONObject jsonObject;

    public TemplateContent(JSONObject jsonObject) {
        this.jsonObject = jsonObject;
    }

    /**
     * @param workWeixinApi 用于上传文件
     */
    public String withValue(Object value, WorkWeixinApi workWeixinApi) {
        return "{" //
                + "    \"control\":\"" + this.getControl() + "\"," //
                + "    \"id\":\"" + this.getId() + "\"," //
                + "    \"value\":" + this.value(value, workWeixinApi) //
                + "}";
    }

    public String getControl() {
        JSONObject _property = this.getJsonObject().getJSONObject("property");
        return _property.getString("control"); // 类型
    }

    /**
     * @param workWeixinApi 用于上传文件
     */
    public String value(Object value, WorkWeixinApi workWeixinApi) {
        if ((null != this.getRequire() && this.getRequire()) //
                && (null == value || ("" + value).trim().isEmpty())) {
            throw new RuntimeException("#63 value required is null, this=" + this);
        }

        String control = this.getControl();

        if ("Text".equalsIgnoreCase(control) || "Textarea".equalsIgnoreCase(control)) {
            Map<String, Object> map = MapUtil.stringObjectMap("text", value + "");
            return Fastjson.toJSONString(map);
        }

        if ("Number".equalsIgnoreCase(control)) {
            Map<String, Object> map = MapUtil.stringObjectMap("new_number", value);
            return Fastjson.toJSONString(map);
        }

        if ("Money".equalsIgnoreCase(control)) {
            return Fastjson.toJSONString(MapUtil.stringObjectMap("new_money", value));
        }

        if ("Date".equalsIgnoreCase(control)) {
            return "{\"date\": {\"type\": \"day\",\"s_timestamp\": \"" + Time.when(value).toSeconds() + "\"}}";
        }

        // 文件 url 逗号分割
        if ("File".equalsIgnoreCase(control)) {
            return this.fileItem(value, workWeixinApi);
        }

        if ("Selector".equalsIgnoreCase(control)) {
            return this.selectorItem(value);
        }

        log.error("#33 control=" + control + ", jsonObject=" + this.getJsonObject());
        throw new RuntimeException("#106 value=" + value + ", this=" + this);
    }

    private String selectorItem(Object value) {
        JSONObject _config = this.getJsonObject().getJSONObject("config");

        JSONObject _selector = _config.getJSONObject("selector");
        JSONArray _options = _selector.getJSONArray("options");

        List<String> _optionKeys = new ArrayList<String>();

        for (Object _each : _options) {
            JSONObject _option = (JSONObject) _each;

            // ID 匹配
            String _optionKey = _option.getString("key");
            if (StringUtil.equals(_optionKey, value)) {
                _optionKeys.add("{\"key\":\"" + _optionKey + "\"}");
            }

            JSONArray _optionValues = _option.getJSONArray("value");

            // 文本匹配
            for (Object _optionValue : _optionValues) {
                String _optionValueText = ((JSONObject) _optionValue).getString("text");
                if (StringUtil.equals(_optionValueText, value)) {
                    _optionKeys.add("{\"key\":\"" + _optionKey + "\"}");
                }
            }
        }

        // 拼接返回
        return "{\"selector\":{\"type\":\"" + _selector.getString("type") + "\",\"options\":[" + StringUtil.join(_optionKeys) + "]}}";
    }

    private String fileItem(Object value, WorkWeixinApi workWeixinApi) {
        if (null == value) { // 为空
            return "{\"files\": [" + StringUtil.join(Collections.EMPTY_LIST, ", ", "{\"file_id\": \"", "\"}") + "]}"; // 传空列表
        }

        // RPC 调用 传 url
        if (value instanceof String && ((String) value).startsWith("http")) { // http 或 https 开头
            return this.httpUrlFile(value, workWeixinApi);
        }

        if (value instanceof JSONObject) {
            return this.jsonFile(value, workWeixinApi);
        }

        log.error("#104 return empty files, value = " + value + ", workWeixinApi=" + workWeixinApi);
        return "{\"files\": [" + StringUtil.join(Collections.EMPTY_LIST, ", ", "{\"file_id\": \"", "\"}") + "]}"; // 传空列表
    }

    private String httpUrlFile(Object value, WorkWeixinApi workWeixinApi) {
        List<String> mediaIds = new ArrayList<String>();

        String[] files = ((String) value).split(",");
        for (String each : files) { // http://test.file.itaojin.cn/2020-12/2b5959571c4b457493309030890ddaa4.jpg
            String fileName = each.substring(each.lastIndexOf('/')); // 文件名
            URL _url = JavaNetUrlUtil.newUrl(each); // 上传文件

            String mediaId = workWeixinApi.uploadMediaReturnId("file", new MultipartEntity(_url, fileName));
            mediaIds.add(mediaId); // 加入集合
        }

        return "{\"files\": [" + StringUtil.join(mediaIds, ", ", "{\"file_id\": \"", "\"}") + "]}";
    }

    private String jsonFile(Object value, WorkWeixinApi workWeixinApi) {
        // 页面 调用 传 json 对象
        JSONObject valueJson = (JSONObject) value;

        List<String> mediaIds = new ArrayList<String>();

        String url = valueJson.getString("url");
        if (StringUtil.isNullOrEmpty(url)) {
            log.error("#86 url=" + url + ", value=" + value + ", this=" + this);

            return "{\"files\": [" + StringUtil.join(mediaIds, ", ", "{\"file_id\": \"", "\"}") + "]}"; // 传空列表
        }

        // 上传文件
        URL _url = JavaNetUrlUtil.newUrl(url);
        String mediaId = workWeixinApi.uploadMediaReturnId("file", new MultipartEntity(_url, valueJson.getString("name")));

        mediaIds.add(mediaId); // 加入集合

        return "{\"files\": [" + StringUtil.join(mediaIds, ", ", "{\"file_id\": \"", "\"}") + "]}";
    }

    public Object valueText(Object value) {
        if ("Selector".equals(this.getControl())) {
            JSONObject _config = this.getJsonObject().getJSONObject("config");
            JSONObject _selector = _config.getJSONObject("selector");
            JSONArray _options = _selector.getJSONArray("options");

            for (Object _each : _options) {
                JSONObject _option = (JSONObject) _each;

                // ID 匹配
                String _key = _option.getString("key");
                JSONArray _values = _option.getJSONArray("value");

                // 传入 key 返回 value
                if (StringUtil.equals(_key, value)) {
                    JSONObject _val = _values.getJSONObject(0);
                    String _text = ((JSONObject) _val).getString("text");
                    return _text;
                }
            }
        }

        // 直接返回本身
        return value;
    }

    public Boolean getRequire() {
        JSONObject _property = this.getJsonObject().getJSONObject("property");
        return NumberUtil.equals(1, _property.getInteger("require")); // 是否必填
    }

    // {"property":{"un_print":0,"control":"Text","require":1,"id":"item-1494250754014","placeholder":[{"text":"","lang":"zh_CN"}],"title":[{"text":"商家名称","lang":"zh_CN"}]}}
    public Object getValue(Map<String, Object> templateContent) {
        Object val = templateContent.get(this.getId());
        if (null != val) {
            return val; // 直接获取
        }

        JSONObject _property = this.getJsonObject().getJSONObject("property");
        JSONArray titles = _property.getJSONArray("title");
        for (Object title : titles) {
            JSONObject _title = (JSONObject) title;
            String titleText = _title.getString("text");
            Object _val = templateContent.get(titleText);
            if (null != _val) {
                return _val;
            }
        }

        // 没有找到对应的值,可能前端传了空值
        log.warn("#123 getValue return null, templateContent = " + templateContent + ", this=" + this);
        return null;
    }

    public Boolean matchId(String id) {
        JSONObject _property = this.getJsonObject().getJSONObject("property");
        String _id = _property.getString("id");

        // 根据 ID
        if (StringUtil.equalsIgnoreCase(_id, id)) {
            return true;
        }

        // 根据 title
        JSONArray _titleArray = _property.getJSONArray("title");
        for (Object _title : _titleArray) {
            String _titleText = ((JSONObject) _title).getString("text");
            if (StringUtil.equalsIgnoreCase(_titleText, id)) {
                return true;
            }
        }

        return false;
    }

    public String getId() {
        JSONObject _property = this.getJsonObject().getJSONObject("property");
        String _id = _property.getString("id");
        return _id;
    }

    public String getTitle() {
        JSONObject _property = this.getJsonObject().getJSONObject("property");
        JSONArray _titleArray = _property.getJSONArray("title");
        String _titleText = ((JSONObject) _titleArray.getJSONObject(0)).getString("text");

        return _titleText;
    }

    public List<Map<String, Object>> getSelectorOptions() {
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        JSONObject _config = this.getJsonObject().getJSONObject("config");
        if (null == _config) {
            return list;
        }

        JSONObject _selector = _config.getJSONObject("selector");
        if (null == _selector) {
            return list;
        }

        JSONArray _options = _selector.getJSONArray("options");
        if (null == _options) {
            return list;
        }

        for (Object each : _options) {
            JSONObject option = (JSONObject) each;
            String key = option.getString("key");

            JSONArray values = option.getJSONArray("value");
            JSONObject value = values.getJSONObject(0);
            String text = value.getString("text");

            list.add(MapUtil.stringObjectMap("id", key, "name", text));
        }

        return list;
    }
}